package ice.server.comm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * JPQL模型对象
 * @author zhangrb
 * @user zhangrb
 * @date 2019-08-26
 */
public class JPSQLModel {

    /**
     * 根实体
     */
    private QueryEntity rootEntity;

    /**
     * 关联的实体，如有多个关联实体，则递归引用，递归自动EntityJoin.nextEntityJoin
     */
    private EntityJoin entityJoin;

    /**
     * 查询结果字段列表
     */
    private List<QueryProperty> result = new ArrayList<>();

    /**
     * 查询条件
     */
    private List<QueryCondition> queryConditions = new ArrayList<>();

    /**
     * 分组条件
     */
    private List<String> groups = new ArrayList<>();

    /**
     * having条件，多个之间使用or进行拼接
     */
    private List<HavingCondition> havingConditions = new ArrayList<>();

    /**
     * 排序条件
     */
    private List<QueryOrder> orders = new ArrayList<>();

    public List<QueryOrder> getOrders() {
        return orders;
    }

    public void setOrders(List<QueryOrder> orders) {
        this.orders = orders;
    }

    public QueryEntity getRootEntity() {
        return rootEntity;
    }

    public void setRootEntity(QueryEntity rootEntity) {
        this.rootEntity = rootEntity;
    }

    public EntityJoin getEntityJoin() {
        return entityJoin;
    }

    public void setEntityJoin(EntityJoin entityJoin) {
        this.entityJoin = entityJoin;
    }

    public List<QueryProperty> getResult() {
        return result;
    }

    public void setResult(List<QueryProperty> result) {
        this.result = result;
    }

    public List<QueryCondition> getQueryConditions() {
        return queryConditions;
    }

    public void setQueryConditions(List<QueryCondition> queryConditions) {
        this.queryConditions = queryConditions;
    }

    public List<String> getGroups() {
        return groups;
    }

    public void setGroups(List<String> groups) {
        this.groups = groups;
    }

    public List<HavingCondition> getHavingConditions() {
        return havingConditions;
    }

    public void setHavingConditions(List<HavingCondition> havingConditions) {
        this.havingConditions = havingConditions;
    }

    /**
     * 实体对象
     */
    public static class QueryEntity {

        /**
         * 实体类的class
         */
        private Class<?> entityClass;

        /**
         * 实体的别名
         */
        private String alias;

        public Class<?> getEntityClass() {
            return entityClass;
        }

        public void setEntityClass(Class<?> entityClass) {
            this.entityClass = entityClass;
        }

        public String getAlias() {
            return alias;
        }

        public void setAlias(String alias) {
            this.alias = alias;
        }
    }

    /**
     * 关联实体对象
     * @author zhangrb
     * @user zhangrb
     * @date 2019-8-26
     */
    public static class EntityJoin {

        /**
         * 要关联的实体
         */
        private QueryEntity entity;

        /**
         * 连接类型
         */
        private JoinType joinType;

        /**
         * 关联的条件，多个之间是有or进行拼接
         */
        private List<JoinCondtion> joinCondtions = new ArrayList<>();

        /**
         * 下个关联的实体对象
         */
        private EntityJoin nextEntityJoin;

        public EntityJoin getNextEntityJoin() {
            return nextEntityJoin;
        }

        public void setNextEntityJoin(EntityJoin nextEntityJoin) {
            this.nextEntityJoin = nextEntityJoin;
        }

        public QueryEntity getEntity() {
            return entity;
        }

        public void setEntity(QueryEntity entity) {
            this.entity = entity;
        }

        public JoinType getJoinType() {
            return joinType;
        }

        public void setJoinType(JoinType joinType) {
            this.joinType = joinType;
        }

        public List<JoinCondtion> getJoinCondtions() {
            return joinCondtions;
        }

    }

    /**
     * 连接类型的枚举
     * @auhtor zhangrb
     * @user zhangrb
     * @date 2019-08-26
     */
    public static enum JoinType {
        INNER_JOIN("join"), LEFT_JOIN("left join"), RIGHT_JOIN("right join");

        private String value;

        private JoinType(String value) {
            this.value = value;
        }

        public String value() {
            return this.value;
        }
    }

    /**
     * 实体的关联条件
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     */
    public static class JoinCondtion {

        /**
         * 连接参数的集合，多个以and进行拼接
         */
        private Map<String, String> joinParam = new HashMap<>();

        public Map<String, String> getJoinParam() {
            return joinParam;
        }
    }

    /**
     * 聚合函数类型的枚举
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     */
    public static enum FunctionType {
        COUNT("count"), AVG("count"), SUM("sum"), MAX("max"), MIN("min");

        private String value;

        private FunctionType(String value) {
            this.value = value;
        }

        public String value() {
            return this.value;
        }
    }

    /**
     * 查询结果字段对象
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     */
    public static class QueryProperty {

        /**
         * 字段名称
         */
        private String name;

        /**
         * 字段别名
         */
        private String alias;

        /**
         * 聚合函数
         */
        private FunctionType funcType;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getAlias() {
            return alias;
        }

        public void setAlias(String alias) {
            this.alias = alias;
        }

        public FunctionType getFuncType() {
            return funcType;
        }

        public void setFuncType(FunctionType funcType) {
            this.funcType = funcType;
        }
    }

    /**
     * 查询条件对象，如果有多个查询参数，使用and进行拼接
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     */
    public static class QueryCondition {

        /**
         * 查询参数，key的格式为：{字段名称}{操作符}
         * @see 操作符参考 Constants类中定义
         */
        private Map<String, Object> queryParams = new HashMap<>();

        public Map<String, Object> getQueryParams() {
            return queryParams;
        }
    }

    /**
     * having条件对象，是HavingParam的集合，使用and进行拼接
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     */
    public static class HavingCondition {

        /**
         * having的参数集合
         */
        private List<HavingParam> havingParams = new ArrayList<>();

        public List<HavingParam> getHavingParams() {
            return havingParams;
        }
    }

    /**
     * having参数对象
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     */
    public static class HavingParam {

        /**
         * having的字段名称
         */
        private String name;

        /**
         * 聚合函数
         */
        private FunctionType funcType;

        /**
         * 比较运算符
         */
        private String op;

        /**
         * 目标值
         */
        private Object value;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public FunctionType getFuncType() {
            return funcType;
        }

        public void setFuncType(FunctionType funcType) {
            this.funcType = funcType;
        }

        public String getOp() {
            return op;
        }

        public void setOp(String op) {
            this.op = op;
        }

        public Object getValue() {
            return value;
        }

        public void setValue(Object value) {
            this.value = value;
        }
    }

    public static class QueryOrder {

        private String name;

        /**
         * true表示升序，false表示降序
         */
        private boolean type;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public boolean getType() {
            return type;
        }

        public void setType(boolean type) {
            this.type = type;
        }
    }
}
